package com.test.A39;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.GenericApplicationContext;


public class A39 {

	public static void main(String[] args) {
	   try {
		   test5(args);
	} catch ( Exception e) {
		e.printStackTrace();
	}
	}
	
	/****
	 * 主类推断
	 * @param args
	 * @throws Exception
	 */
	private static void test5(String[] args)  throws Exception {
		 System.out.println("1. 演示获取 Bean Definition 源");
	        SpringApplication spring = new SpringApplication(A39.class);
	        Set<String> set =new HashSet();
	        set.add("classpath:b01.xml");
	        spring.setSources(set);  //读取其他的源
	        System.out.println("2. 演示推断应用类型");
	        Method deduceFromClasspath = WebApplicationType.class.getDeclaredMethod("deduceFromClasspath");
	        deduceFromClasspath.setAccessible(true);
	        System.out.println("\t应用类型为:"+deduceFromClasspath.invoke(null));
	        System.out.println("3. 演示 ApplicationContext 初始化器");
	        spring.addInitializers(applicationContext -> {
	            if (applicationContext instanceof GenericApplicationContext) {
	            	GenericApplicationContext gac =(GenericApplicationContext) applicationContext;
	                gac.registerBean("bean3", Bean3.class);//初始化器  把bean3给初始化 
	            }
	        });
	        
	        System.out.println("4. 演示监听器与事件");
	        spring.addListeners(event -> System.out.println("\t事件为:" + event.getClass()));
	        
	        System.out.println("5. 演示主类推断");
	        Method deduceMainApplicationClass = SpringApplication.class.getDeclaredMethod("deduceMainApplicationClass");
	        deduceMainApplicationClass.setAccessible(true);
	        System.out.println("\t主类是："+deduceMainApplicationClass.invoke(spring));
	        
	        ConfigurableApplicationContext context = spring.run(args);
	        for (String name : context.getBeanDefinitionNames()) {
	            System.out.println("name: " + name + " 来源：" + context.getBeanFactory().getBeanDefinition(name).getResourceDescription());
	        }
	        context.close();
		
	}
	
	
	/***
	 * 监听器与事件
	 * @param args
	 * @throws Exception
	 */
	private static void test4(String[] args)  throws Exception {
		 System.out.println("1. 演示获取 Bean Definition 源");
	        SpringApplication spring = new SpringApplication(A39.class);
	        Set<String> set =new HashSet();
	        set.add("classpath:b01.xml");
	        spring.setSources(set);  //读取其他的源
	        System.out.println("2. 演示推断应用类型");
	        Method deduceFromClasspath = WebApplicationType.class.getDeclaredMethod("deduceFromClasspath");
	        deduceFromClasspath.setAccessible(true);
	        System.out.println("\t应用类型为:"+deduceFromClasspath.invoke(null));
	        System.out.println("3. 演示 ApplicationContext 初始化器");
	        spring.addInitializers(applicationContext -> {
	            if (applicationContext instanceof GenericApplicationContext) {
	            	GenericApplicationContext gac =(GenericApplicationContext) applicationContext;
	                gac.registerBean("bean3", Bean3.class);//初始化器  把bean3给初始化 
	            }
	        });
	        
	        System.out.println("4. 演示监听器与事件");
	        spring.addListeners(event -> System.out.println("\t事件为:" + event.getClass()));
	        
	        ConfigurableApplicationContext context = spring.run(args);
	        for (String name : context.getBeanDefinitionNames()) {
	            System.out.println("name: " + name + " 来源：" + context.getBeanFactory().getBeanDefinition(name).getResourceDescription());
	        }
	        context.close();
		
	}
	
	/***
	 * 演示 ApplicationContext 初始化器
	 * @param args
	 * @throws Exception
	 */
	private static void test3(String[] args)  throws Exception {
		 System.out.println("1. 演示获取 Bean Definition 源");
	        SpringApplication spring = new SpringApplication(A39.class);
	        Set<String> set =new HashSet();
	        set.add("classpath:b01.xml");
	        spring.setSources(set);  //读取其他的源
	        System.out.println("2. 演示推断应用类型");
	        Method deduceFromClasspath = WebApplicationType.class.getDeclaredMethod("deduceFromClasspath");
	        deduceFromClasspath.setAccessible(true);
	        System.out.println("\t应用类型为:"+deduceFromClasspath.invoke(null));
	        System.out.println("3. 演示 ApplicationContext 初始化器");
	        spring.addInitializers(applicationContext -> {
	            if (applicationContext instanceof GenericApplicationContext) {
	            	GenericApplicationContext gac =(GenericApplicationContext) applicationContext;
	                gac.registerBean("bean3", Bean3.class);//初始化器  把bean3给初始化 
	            }
	        });
	        ConfigurableApplicationContext context = spring.run(args);
	        for (String name : context.getBeanDefinitionNames()) {
	            System.out.println("name: " + name + " 来源：" + context.getBeanFactory().getBeanDefinition(name).getResourceDescription());
	        }
	        context.close();
		
	}

	/****
	 * 演示推断应用类型
	 * @param args
	 * @throws Exception
	 */
	private static void test2(String[] args) throws Exception {
		   System.out.println("1. 演示获取 Bean Definition 源");
	        SpringApplication spring = new SpringApplication(A39.class);
	        Set<String> set =new HashSet();
	        set.add("classpath:b01.xml");  //初始化bean1
	        spring.setSources(set);  //读取其他的源
	        System.out.println("2. 演示推断应用类型");
	        Method deduceFromClasspath = WebApplicationType.class.getDeclaredMethod("deduceFromClasspath");
	        deduceFromClasspath.setAccessible(true);
	        System.out.println("\t应用类型为:"+deduceFromClasspath.invoke(null));
	        ConfigurableApplicationContext context = spring.run(args);
	        for (String name : context.getBeanDefinitionNames()) {
	            System.out.println("name: " + name + " 来源：" + context.getBeanFactory().getBeanDefinition(name).getResourceDescription());
	        }
	        context.close();
		
	}


	/****
	 * 演示获取 Bean Definition 源    可以通过添加配置文件的方式得到其他的源
	 * 需要TomcatServletWebServerFactory
	 * @param args
	 */
	public static void test1(String[] args) {
        System.out.println("1. 演示获取 Bean Definition 源");
        SpringApplication spring = new SpringApplication(A39.class);
        Set<String> set =new HashSet();
        set.add("classpath:b01.xml");
        spring.setSources(set);  //读取其他的源
        ConfigurableApplicationContext context = spring.run(args);
        for (String name : context.getBeanDefinitionNames()) {
            System.out.println("name: " + name + " 来源：" + context.getBeanFactory().getBeanDefinition(name).getResourceDescription());
        }
        context.close();
	}
	
	  static class Bean1 {

	    }

	    static class Bean2 {

	    }

	    static class Bean3 {

	    }

	    @Bean
	    public Bean2 bean2() {
	        return new Bean2();
	    }

	    @Bean
	    public TomcatServletWebServerFactory servletWebServerFactory() {
	        return new TomcatServletWebServerFactory();
	    }
}
